<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /*
            总结：思路
              先自己创建一个Promise ，再创一个实例 p ，p的then方法里的res函数用 this.resolveFn = onResolved指代，把this.resolveFn = undefined放在Promise的属性下保存下来，调用this.resolveFn放在#_resolve私有方法下

              方法一：如果先执行resolve函数，要把调用resolve设为异步，不然会在p.then提前执行，保存的resolveFn在后面执行，没有作用。
              方法二：把放在#_resolve私有方法下的this.resolveFn设为异步
      */
      class MyPromise {
        constructor(handle) {
          // handle ---> (resolve,reject)=>{}
          this["[[PromiseState]]"] = "pendding";
          this["[[PromiseResult]]"] = undefined;
          // 不用bind是undefined，使用则是p实例
          handle(this.#_resolve.bind(this), this.#_reject.bind(this));
          this.resolveFn = undefined; // 保存 onResolved 函数
          this.rejectFn = undefined; // 保存onRejected 函数
        }

        #_resolve(val) {
          // 私有方法 需要在前面加上#号，只能类的内部调用外部不能调用
          this["[[PromiseState]]"] = "fulfilled";
          this["[[PromiseResult]]"] = val;
          // 内部延迟执行
          setTimeout(() => {
            this.resolveFn(val); //  在调取 resolve的时候执行 保存的onResolved函数
          });
        }

        #_reject(err) {
          this["[[Promisestate]]"] = "rejected";
          this["[[PromiseResult]]"] = err;
          setTimeout(() => {
            this.rejectFn(err);
          });
          setTimeout(() => {
            throw new Error(err); //抛出错误
          });
        }

        then(onResolved, onRejected) {
          console.log("then方法执行了");
          // onResolved(); // 直接执行还不行
          this.resolveFn = onResolved; // resolveFn:(res)=>{函数体}
          this.rejectFn = onRejected;
        }
      }

      // 执行顺序 会先执行 resolve函数 ，之后执行then方法 然后才赋值 onResolved 级 onRejected
      let p = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          resolve("success");
        }, 1000);
      });
      p.then(
        (res) => {
          console.log("执行了onResolved", res);
        },
        (err) => {}
      ); // 调用 类里then方法；
    </script>
  </body>
</html>
